﻿using Sasa.QualityTools.CodeAnalysis.SearchEngine.Processing.Tokens;
using System;
using System.Collections.Generic;

namespace Sasa.QualityTools.CodeAnalysis.SearchEngine.Processing
{
    internal class Tokenizer
    {
        internal IEnumerable<IToken> Tokenize(string text)
        {
            if (String.IsNullOrWhiteSpace(text))
            {
                return new List<IToken>();
            }

            List<IToken> tokens = new List<IToken>();
            Queue<char> chars = new Queue<char>(text);
            List<char> word = new List<char>();

            while (chars.Count > 0)
            {
                char c = chars.Dequeue();
                if (c == '"' || c == '\'')
                {
                    while (chars.Count > 0 && chars.Peek() != '"' && chars.Peek() != '\'')
                    {
                        word.Add(chars.Dequeue());
                    }
                    if (chars.Count > 0)
                    {
                        chars.Dequeue();
                    }
                }
                else if (c == '(' || c == ')')
                {
                    word.Add(c);
                }
                else if (!Char.IsWhiteSpace(c))
                {
                    word.Add(c);
                    while (chars.Count > 0 && !Char.IsWhiteSpace(chars.Peek()) && chars.Peek() != '(' && chars.Peek() != ')')
                    {
                        word.Add(chars.Dequeue());
                    }
                }

                if (word.Count > 0)
                {
                    tokens.Add(CreateToken(new String(word.ToArray())));
                    word.Clear();
                }
            }

            return tokens;
        }

        private IToken CreateToken(string value)
        {
            IToken token = null;

            switch (value.ToUpper())
            {
                case "(": token = new LPar(); break;
                case ")": token = new RPar(); break;
                case "AND": token = new And(); break;
                case "OR": token = new Or(); break;
                default: token = new Word(); break;
            }
            token.Value = value;

            return token;
        }
    }
}
